﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ApiServer.AppOotions;
using ApiServer.RpcImpl;
using ApiServer.SubscribeService;
using ApiService;
using Kdfafa.Start.FeeBill.BLL.Service;
using KJFrame.Core.Log;
using KJFrame.Core.Rpc.Protocol;
using KJFrame.Core.Rpc.Protocol.Serializers;
using KJFrame.Core.Rpc.Server;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.PlatformAbstractions;
using Swashbuckle.AspNetCore.Swagger;

namespace ApiServer
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        /// <summary>
        /// 注册服务
        /// </summary>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "server demo", Version = "v1" });
                var xmls = GetXmls();
                if (xmls != null)
                {
                    foreach (var item in xmls)
                    {
                        c.IncludeXmlComments(item);
                    }
                }
            });

            #region 读取apollo的json配置
            //读取apollo的json配置
            //apollo读取json给对象，需要使用NuGet安装Tuhu.Extensions.Configuration.ValueBinder.Json包
            services.ConfigureJsonValue<CachedOptions>(Configuration.GetSection("CachedOptions"));
            services.ConfigureJsonValue<ComplexOptions>(Configuration.GetSection("ComplexOptions"));
            services.ConfigureJsonValue<TableOptions>(Configuration.GetSection("TableOptions"));
            #endregion
            #region 自定义构造函数配置
            //自定义委托配置
            services.Configure<CustomOptions>((option) =>
            {
                option.AppUserID = "小小";
                option.AppUserNo = 10923;
            });
            #endregion
            #region 读josn文件的命名配置
            services.Configure<NamedCachedOptions>("Test1", Configuration.GetSection("NamedCachedOptionsList:TestDemo"));
            services.Configure<NamedCachedOptions>("Test2", Configuration.GetSection("NamedCachedOptionsList:DevDemo"));
            #endregion


            #region 从apollo获取 cap连接字符串
            var capConction = Configuration.GetSection("CapConection")?.Value;
            if (string.IsNullOrWhiteSpace(capConction))
                capConction = "Integrated Security = False; server = 192.168.1.109; database = cap; User ID = sa; Password = 198603yang; Connect Timeout = 30";
            #endregion

            #region 注册CAP服务

            //注册继承自ICapSubscribe接口的订阅必须在AddCap之前进行注册，才会被扫描到
            //继承自Controller的订阅无需注册即可被扫描到
            services.AddTransient<ICapServerService, CapServerService>();

            //下面语句用于开启支持使用EntityFramework，使用此方案时，无需配置UseSqlServer或者Mysql
            //services.AddDbContext<AppDbContext>();

            services.AddCap(x =>
            {
                #region 配置Cap的本地消息记录库，用于服务端保存Published消息记录表；客户端保存Received消息记录表

                #region  1，此方法默认使用的数据库Schema为Cap；2，要求最低sql server2012(因为使用了Dashboard的sql查询语句使用了Format新函数)
                //x.UseSqlServer("Integrated Security=False;server=192.168.1.109;database=cap;User ID=sa;Password=198603yang;Connect Timeout=30"); 
                #endregion

                //1，此方法可以指定是否使用sql server2008,数据库Schema,链接字符串
                x.UseSqlServer((options) =>
                {

                    //数据库连接字符串
                    //options.ConnectionString = "Integrated Security=False;server=192.168.1.109;database=cap;User ID=sa;Password=198603yang;Connect Timeout=30";
                    options.ConnectionString = capConction;
                    //标记使用的是SqlServer2008引擎(此处设置的是2008,因为192.168.1.109数据库是2008)
                    options.UseSqlServer2008();

                    //Cap默认使用的数据库Schema为cap;此处可以指定使用自己的数据库Schema
                    options.Schema = "Cap";
                });

                #endregion

                //使用Kafka作为底层之间的消息发送
                x.UseKafka("192.168.1.230:9092,192.168.1.231:9092,192.168.1.232:9092");

                //使用Dashboard，这是一个Cap的可视化管理界面；默认地址:http://localhost:端口/cap
                x.UseDashboard();

                //设置默认订阅topic分组名，不设置的时候默认为订阅topic组名为："cap.queue."+当前程序集名(" ApiServer")
                //x.DefaultGroup = "WDB";

                //失败后的重试次数，默认50次；在FailedRetryInterval默认60秒的情况下，即默认重试50*60秒(50分钟)之后放弃失败重试
                //x.FailedRetryCount = 10;

                //失败后的重拾间隔，默认60秒
                //x.FailedRetryInterval = 30;

                //设置成功信息的删除时间默认24*3600秒
                //x.SucceedMessageExpiredAfter = 60 * 60;

                //用于指定Cap版本作为数据版本隔离
                //x.Version = "v1";

                //失败之后的回调函数：达到失败重试的上线时才触发此事件
                x.FailedThresholdCallback = FailCallBack;

            });
            #endregion

            #region log4
            services.AddKJLog4net();
            #endregion

            #region RPC服务器与服务注册
            #region 使用buf序列化Rpc服务器
            //services.AddRpcServer(option =>
            //{
            //    Configuration.GetSection(RpcConfigInformation.RpcServerConfigSectionName).Bind(option);
            //});
            #endregion
            #region 使用Json序列化Rpc服务器
            services.AddRpcServer<JsonSerializer>(option =>
            {
                Configuration.GetSection(RpcConfigInformation.RpcServerConfigSectionName).Bind(option);
            });
            #endregion
            services.AddScoped<IUserService, UserService>();
            services.AddScoped<IRoleService, RoleService>();
            services.AddScoped<IFeeBillService, FeeBillService>();

            #endregion
        }

        /// <summary>
        /// 注册管道
        /// </summary>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //启用中间件服务生成Swagger作为JSON终结点
            app.UseSwagger();
            //启用中间件服务对swagger-ui，指定Swagger JSON终结点
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "server api");
            });
            app.UseMvc();
        }

        public void FailCallBack(DotNetCore.CAP.Models.MessageType messageType, string messageName, string messageContent)
        {
            Console.WriteLine($"回调信息:messageType:{messageType};messageName:{messageName};messageContent:{messageContent}");
        }

        /// <summary>
        /// 获取 SwaggerUI的Document文档注释
        /// </summary>
        /// <returns></returns>
        private string[] GetXmls()
        {
            var basePath = PlatformServices.Default.Application.ApplicationBasePath;
            var fileList = Directory.GetFiles(basePath, "*.xml");
            return fileList;
        }
    }
}
